package org.ph.share.lock.test.thread2;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

/**
 * <p>wait()与 notify()</p>
 * <p>1.调用以上俩个方法必须在synchronized修饰的代码块中执行(必须为锁的主人)</p>
 * <p>2.使用wait()方法后,该线程进入waitSet队列等待 notify [唤醒],当唤醒后需要重新竞争来获取锁</p>
 * <p>3.wait()与sleep()的区别</p>
 * <p>     1.对象不同，Object,Thread</p>
 * <p>     2.sleep不会释放锁，而wait会</p>
 * <p>4.假唤醒可以使用while循环来处理</p>
 * @author Hush.
 * @since 2023/5/18 12:53
 */
@Slf4j
public class Worker_wn {
    static final Object room = new Object();
    static boolean CIGAR_FLAG = false;
    static boolean MONEY_100000_FLAG = false;

    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (room) {
                log.info("worker-1,有烟么?:{}", CIGAR_FLAG);
                try {
                    // 使用while来防止假唤醒
                    while (!CIGAR_FLAG) {
                        log.info("无烟？摆烂。休息去了");
                        room.wait();
                    }
                    log.info("那我干一会吧。");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }, "worker-1").start();

        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                synchronized (room) {
                    if (MONEY_100000_FLAG) {
                        log.info("我干，我干，我干");
                    } else {
                        try {
                            log.info("no money not to do .{}", MONEY_100000_FLAG);
                            room.wait();
                            if (MONEY_100000_FLAG) {
                                log.info("钱到位，我干，我干，我干");
                            } else {
                                log.info("把我唤醒，也没个钱？干鸡毛");
                            }
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }, "worker-卷王" + i).start();
        }
        new Thread(() -> {
            try {
                // 模拟拿钱拿烟的耗时
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            synchronized (room) {
                CIGAR_FLAG = true;
                log.info("工人爷爷，您的烟到了");
                // MONEY_100000_FLAG = true;
                // log.info("工人爷爷，您的钱到了");
                // room.notify();
                room.notifyAll();

            }
        }, "老板").start();
    }
}
